package com.yc.navy.springmvc.core;




import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.yc.navy.springmvc.core.annotation.ResponseBody;
import com.yc.navy.springmvc.core.annotation.RestController;
import com.yc.navy.springmvc.util.StringUtil;
/**
 * 请求分发器
 * @author 主机
 *
 */
public class DispatcherServlet extends HttpServlet{
	
	private static final long serialVersionUID = -6316324639080952324L;
	
	private String contextConfigLocation = "application.properties";
	private SpringFrameworkCore cfc;
	
	@Override
	public void init(ServletConfig config) throws ServletException {
		String temp = config.getInitParameter("contextConfigLocation");
		if (!StringUtil.checkNull(temp)) {
			contextConfigLocation = temp;
		}
		// 解析配置文件获取基址扫描路径，扫描解析
		cfc = new SpringFrameworkCore(contextConfigLocation);
	}

	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 获取请求的资源地址
		String url = request.getRequestURI(); // /springmvc/member/reg
		// 获取解析请求的项目名称	// /springmvc/demo/finds
		String contextPath = request.getContextPath();
		//获取真正的资源路径	///demo/finds
		url = url.replaceFirst(contextPath, "");
		// 判断请求路径是否有资源
		if(url.contains("?")) {
			url = url.substring(0, url.indexOf("?"));
		}
		
		//请求路径有对应的处理方法吗？
		HandlerMapperInfo handerMapperInfo = cfc.getMapper(url);
		// 如果没有则当成静态资源处理
		if(handerMapperInfo == null ) {
			HandlerResponse.staticResource(response, request.getServletContext().getRealPath("") + url.substring(1));
			return;
		}
				
		// 获取请求方法是否跟方法上配置方式一致
		String handerMethod = handerMapperInfo.getRequestMethod();	
		if(handerMethod != null && handerMethod.isEmpty() 
				&& !handerMethod.equals(request.getMethod())) {	//有指定请求方法且与当前请求方式不相同
			HandlerResponse.sendStr(response, "请求方法不支持");
			return;
		}
				
		try {
			// 如果有对应的处理方法，激活这个方法 -> 需要获取这个方法的形参列表值-> 从请求中的来
			Method resultMethod = handerMapperInfo.getMethod();
			Object[] args = HandlerRequest.handle(request, response, resultMethod);
			Object result = resultMethod.invoke(handerMapperInfo.getObj(), args );
			// 激活运行方法获取返回值
					
			//判断这个方法上或方法所在的类上有没有@ResponseBody注解或者这个方法所在的类上是否是@RestController注解，如果有说明以json格式返回
			if(resultMethod.isAnnotationPresent(ResponseBody.class) || resultMethod.getClass().isAnnotationPresent(RestController.class)) {
				HandlerResponse.sendJson(response, result);
		        return;
			}
			//如果没有则将这个结果强制转成字符串，判断字符串的开始是否有redirect：如果是则重定向否则内部转发
			String path = String.valueOf(result);
			if(path.startsWith("redirect:")) {
				path = path.replaceFirst("redirect:", "");
				if(path.startsWith("/")) {
					path = contextPath + path;
				}
				response.sendRedirect(path);
				return;
			}
			request.getRequestDispatcher(path).forward(request, response);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
